﻿// pch.cpp: 与预编译标头对应的源文件

#include "pch.h"

// 当使用预编译的头时，需要使用此源文件，编译才能成功。
// 加载图片资源（传入待加载图片的资源id和资源类型，返回加载到图片的Image对象指针）
Gdiplus::Image* LoadFromRes(UINT nResID, LPCTSTR lpszResType, HINSTANCE hInstance)
{
	Gdiplus::Image* pImage = NULL;

	ASSERT(lpszResType);

	// 通过资源id和类型找到资源数据块，注意：这个资源类型就是在资源中添
		// 加文件时提示输入的资源类型标识串，比如下面代码中的“PNG”和“ZIP”
	HRSRC hPic = FindResource(hInstance, MAKEINTRESOURCE(nResID), lpszResType);
	HANDLE hResData = NULL;
	if (!hPic || !(hResData = LoadResource(hInstance, hPic)))
	{
		::OutputDebugString(_T("Load (resource): Error loading resource: %d\n"));
		return NULL;
	}

	// 获取资源数据的大小，供GlobalAlloc使用
	DWORD dwSize = SizeofResource(hInstance, hPic);

	// 根据资源数据大小，分配HGLOBAL内存
	HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD, dwSize);
	if (!hGlobal)
	{
		::OutputDebugString(_T("Load (resource): Error allocating memory\n"));
		FreeResource(hResData);
		return NULL;
	}

	char* pDest = reinterpret_cast<char*> (GlobalLock(hGlobal));
	char* pSrc = reinterpret_cast<char*> (LockResource(hResData)); // 锁住资源
	if (!pSrc || !pDest)
	{
		::OutputDebugString(_T("Load (resource): Error locking memory\n"));
		GlobalFree(hGlobal);
		FreeResource(hResData);
		return NULL;
	};

	// 将资源数据拷贝到HGLOBAL内存中，用于创建流
	memcpy(pDest, pSrc, dwSize);
	FreeResource(hResData);
	GlobalUnlock(hGlobal);

	IStream* pStream = NULL;
	if (CreateStreamOnHGlobal(hGlobal, TRUE, &pStream) != S_OK)
	{
		return NULL;
	}

	pImage = Gdiplus::Image::FromStream(pStream);

	// 要加上这一句，否则由GlobalAlloc得来的hGlobal内存没有被释放，导致内存泄露，由于
	// CreateStreamOnHGlobal第二个参数被设置为TRUE，所以调用pStream->Release()会自动
	// 将hGlobal内存（参见msdn对CreateStreamOnHGlobal的说明），by zzx 2014/04/17	pStream->Release();

	return pImage;
}
